#include "bsp_hp_rtc.h"

/**
 * @brief RTC_HP 初始化
 *
 */
void RTC_HP_Init(void) {
  CCM->CCGR5 |= (0x3 << 0);
  RTC_HP_Disable();
  /*
   * 设置HPCOMR寄存器
   * bit[31] 1 : 允许访问SNVS寄存器，一定要置1
   * bit[8]  1 : 此位置1，需要签署NDA协议才能看到此位的详细说明，
   *             这里不置1也没问题
   */
  SNVS->HPCOMR |= (1 << 31) | (1 << 8);

#if 0
  struct rtc_datetime rtcdate;

  rtcdate.year = 2024U;
  rtcdate.month = 12U;
  rtcdate.day = 1U;
  rtcdate.hour = 13U;
  rtcdate.minute = 40;
  rtcdate.second = 0;
  RTC_HP_Setdatetime(&rtcdate); // 初始化时间和日期
#endif

  RTC_HP_Enable();
}

/*
 * @description		: 获取当前时间
 * @param - datetime: 获取到的时间，日期等参数
 * @return 			: 无
 */
void RTC_HP_Getdatetime(rtc_datetime *datetime) {
  // unsigned int seconds = 0;
  u64 seconds;
  seconds = RTC_HP_GetSeconds();
  rtc_convertseconds_to_datetime(seconds, datetime);
}

/**
 * @brief 获取RTC当前秒数
 *
 * @return unsigned int 当前秒数
 */
unsigned int RTC_HP_GetSeconds(void) {
  unsigned int seconds_old = 0;
  unsigned int seconds_new = 0;

  seconds_old = (SNVS->HPRTCMR << 17) | (SNVS->HPRTCLR >> 15);
  while (1) {
    seconds_new = (SNVS->HPRTCMR << 17) | (SNVS->HPRTCLR >> 15);
    if (seconds_old == seconds_new) {
      break;
    } else {
      seconds_old = seconds_new;
    }
  }
  return seconds_new;
}

/**
 * @brief 设置时间和日期
 *
 * @param datetime 要设置的日期和时间
 */
void RTC_HP_Setdatetime(rtc_datetime *datetime) {

  u64 seconds = 0;
  unsigned int tmp = SNVS->HPCR;

  RTC_HP_Disable(); /* 设置寄存器HPRTCMR和HPRTCLR的时候一定要先关闭RTC */

  /* 先将时间转换为秒         */
  seconds = rtc_coverdate_to_seconds(datetime);

  SNVS->HPRTCMR = (unsigned int)(seconds >> 17); /* 设置高15位 */
  SNVS->HPRTCLR = (unsigned int)(seconds << 15); /* 设置低17位 */

  /* 如果此前RTC是打开的在设置完RTC时间以后需要重新打开RTC */
  if (tmp & 0x1)
    RTC_HP_Enable();
}

/**
 * @brief 开启RTC_HP
 *
 */
void RTC_HP_Enable(void) {
  /*
   * LPCR寄存器bit0置1，使能RTC
   */
  SNVS->HPCR |= 1 << 0;
  while (!(SNVS->HPCR & 0X01))
    ; // 等待使能完成
}

/**
 * @brief 关闭RTC_HP
 *
 */
void RTC_HP_Disable(void) {
  /*
   * LPCR寄存器bit0置0，关闭RTC
   */
  SNVS->HPCR &= ~(1 << 0);
  while (SNVS->HPCR & 0X01)
    ; // 等待关闭完成
}